package com.byt;

import cn.hutool.core.util.RuntimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import oshi.SystemInfo;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class RAMServer1 {
    private static Logger logger = LoggerFactory.getLogger(RAMServer1.class);
    static int size = 1024 * 1024 * 60;
    static BigDecimal g = new BigDecimal(size);
    /**
     * 内存控制
     */
    public static void RAM(){
        List<byte[]> memory = new ArrayList<>();
        while (true) {
            try {
                String command = getCommand();
                int control = RAMInfo(command);
                // 模拟动态内存释放
                if(control ==0){
                    logger.info("内存满了，跳出："+memory.size());
                    memory.clear();
                    Thread.sleep(10000);
                    break;
                }
                logger.info("增加内存一次："+memory.size());
                memory.add(new byte[size]);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 保留多少个对象在内存中
     */
    private static int control(){
        BigDecimal g = new BigDecimal(size);
        SystemInfo si = new SystemInfo();
        HardwareAbstractionLayer hal = si.getHardware();
        GlobalMemory memory = hal.getMemory();
        /**
         * 默认占用剩余内存的百分之55%
         * 当剩余内存小于总内存的百分之30后不再占用
         */
        //剩余内存
        BigDecimal free = new BigDecimal(String.valueOf(memory.getAvailable())).divide(g,0,BigDecimal.ROUND_HALF_UP);
        //查询总内存的30%
        BigDecimal total = new BigDecimal(String.valueOf(memory.getTotal())).multiply(new BigDecimal("0.3")).divide(g,0,BigDecimal.ROUND_HALF_UP);
        if(total.compareTo(free)>=0){
            return 0;
        }
        //控制内存到剩余内存的
        BigDecimal control = free.multiply(new BigDecimal("0.8")).setScale(0,BigDecimal.ROUND_HALF_UP);
        return control.intValue();
    }

    /**
     * 内存占用
     * @return
     */
    public static int RAMInfo(String command){
        //总内存
        BigDecimal totalNum = totalNum(command);
        //用掉的内存
        BigDecimal usedNum = usedNum(command);
        //最高可消耗的内存
        BigDecimal highestConsume = highestConsume(command);
        //内存占有率
        BigDecimal res = usedNum.divide(totalNum,0,BigDecimal.ROUND_HALF_UP);
        if(new BigDecimal("60").compareTo(res)>0){
            BigDecimal consumeNum = BigDecimal.ZERO;
            if(highestConsume.compareTo(usedNum)>0){
                consumeNum = highestConsume.subtract(usedNum);
            }
            return consumeNum.intValue();
        }
        return 0;
    }

    /**
     * 获取Linux内存信息
     * @return
     */
    private static String getCommand(){
        String command1 = "top -b -n 1 | grep Mem";
        String[] command = { "/bin/sh", "-c", command1 };
        return RuntimeUtil.execForStr(command);
    }

    /**
     * 获取Linux总内存信息
     * @return
     */
    private static BigDecimal totalNum(String command){
        String total = command.substring(command.indexOf(":") + 1, command.indexOf("total")).replace(" ","");
        return new BigDecimal(total).multiply(new BigDecimal("1024")).divide(g,0,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 获取Linux已使用内存信息
     * @return
     */
    private static BigDecimal usedNum(String command){
        String used = command.substring(command.indexOf("free,") + 5, command.indexOf("used,")).replace(" ","");
        return new BigDecimal(used).multiply(new BigDecimal("1024")).divide(g,0,BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 消耗最高内存
     * @return
     */
    public static BigDecimal highestConsume(String command){
        BigDecimal totalNum = totalNum(command);
        return totalNum.multiply(new BigDecimal("60")).divide(new BigDecimal("100"),0,BigDecimal.ROUND_HALF_UP);
    }

}
